package com.ledi.guns.modular.ledipay.controller;

import static com.ledi.guns.core.support.HttpKit.getIp;
import io.swagger.annotations.Api;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.ledi.guns.common.exception.AppCheckException;
import com.ledi.guns.common.persistence.dao.UserMapper;
import com.ledi.guns.common.persistence.model.User;
import com.ledi.guns.common.util.StringUtil;
import com.ledi.guns.config.properties.GunsProperties;
import com.ledi.guns.core.base.controller.BaseController;
import com.ledi.guns.core.base.tips.SuccessTip;
import com.ledi.guns.core.base.tips.Tip;
import com.ledi.guns.core.log.LogManager;
import com.ledi.guns.core.log.factory.LogTaskFactory;
import com.ledi.guns.core.node.MenuNode;
import com.ledi.guns.core.redis.KeyValueDAO;
import com.ledi.guns.core.shiro.ShiroKit;
import com.ledi.guns.core.shiro.ShiroUser;
import com.ledi.guns.core.support.HttpKit;
import com.ledi.guns.core.util.ApiMenuFilter;
import com.ledi.guns.core.util.KaptchaUtil;
import com.ledi.guns.core.util.SystemConstans;
import com.ledi.guns.core.util.ToolUtil;
import com.ledi.guns.modular.system.dao.MenuDao;

/**
 * 文件名称： com.ledi.guns.modular.ledipay.controller.LoginController.java<br/>
 * 初始作者： 钟小平<br/>
 * 创建日期： 2017年11月30日<br/>
 * 功能说明： 登录控制器 <br/>
 * =================================================<br/>
 * 修改记录：<br/>
 * 修改作者 日期 修改内容<br/>
 * ================================================<br/>
 * Copyright (乐迪教育科技有限公司-幼儿事业部) 2017-2018.All rights reserved.<br/>
 */
@RestController
@Api
@RequestMapping("/restApi")
public class LoginApiController extends BaseController {

	@Autowired
	MenuDao menuDao;

	@Autowired
	UserMapper userMapper;

	@Resource
	private GunsProperties gunsProperties;

	@Autowired
	Producer producer;

	@Autowired
	KeyValueDAO keyValueDAO;

	/**
	 * 登录验证
	 *
	 * @throws IOException
	 */
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public Tip login(HttpServletRequest request, HttpServletResponse response) throws IOException {

		String url = request.getRequestURI();
		if (url.startsWith("/restApi")) {

			if (ShiroKit.isAuthenticated() || ShiroKit.getUser() != null) {
				return SuccessTip.buildSuccess();
			} else {
				throw new AppCheckException("system.user.notLogin.code", "system.user.notLogin.message");
			}

		} else {
			response.sendRedirect("/login");
		}

		return null;

	}

	/**
	 * @api {POST} /restApi/login 登录
	 * @apiVersion 1.0.0
	 * @apiGroup system
	 * @apiName login
	 * @apiParam {String } username 用户名
	 * @apiParam {String } password 密码
	 * @apiParam {String } remember 记住我（on:开启，off关闭）
	 * @apiParam {String } kaptcha 验证码（默认不启用）
	 * @apiSuccess {String} account 账户
	 * @apiSuccess {Long} deptId 部门id
	 * @apiSuccess {Long} id 用户id
	 * @apiSuccess {String} name 用户名称
	 * @apiSuccess {JsonArray} roleNames 部门名称数字
	 * @apiSuccessExample {json} Success-Response:
	 *                    HTTP/1.1 200 OK
	 *                    {
	 *                    "code": 200,
	 *                    "data": {
	 *                    "account": "sunwu",
	 *                    "deptId": 29,
	 *                    "deptName": "员工后台",
	 *                    "id": 47,
	 *                    "name": "孙武",
	 *                    "roleList": [
	 *                    8,
	 *                    9
	 *                    ],
	 *                    "roleNames": [
	 *                    "员工管理员",
	 *                    "代理商管理员"
	 *                    ]
	 *                    },
	 *                    "message": "成功"
	 *                    }
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public Object loginVali() {

		String username = super.getPara("username").trim();
		String password = super.getPara("password").trim();
		String remember = super.getPara("remember");
		Subject subject = SecurityUtils.getSubject();
		// 验证验证码是否正确
		if (KaptchaUtil.getKaptchaOnOff()) {
			String kaptcha = super.getPara("kaptcha").trim();
			String code = (String) super.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
			if (ToolUtil.isEmpty(kaptcha) || !kaptcha.equalsIgnoreCase(code)) {
				throw new AppCheckException("system.user.kaptcha.code", "system.user.kaptcha.message");
			}
		}

		Subject currentUser = ShiroKit.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray());

		if ("on".equals(remember)) {
			token.setRememberMe(true);
		} else {
			token.setRememberMe(false);
		}
		try {
			Map<String, Object> columnMap = new HashMap<String, Object>();
			columnMap.put("account", username);
			List<User> userList = userMapper.selectByMap(columnMap);
			if (userList.size() > 0) {
				User u = userList.get(0);
				if (u.getStatus() == SystemConstans.USER_STATUS_DELETE) {
					throw new AppCheckException("system.user.delete.code", "system.user.delete.message");
				}
			}

			currentUser.login(token);
		} catch (IncorrectCredentialsException e) {
			throw new AppCheckException("system.user.noteixt.code", "system.user.noteixt.message");
		} catch (LockedAccountException e) {
			throw new AppCheckException("system.user.freze.code", "system.user.freze.message");
		} catch (AuthenticationException e) {
			throw new AppCheckException("system.user.noteixt.code", "system.user.noteixt.message");
		}
		ShiroUser shiroUser = ShiroKit.getUser();
		super.getSession().setAttribute("shiroUser", shiroUser);
		super.getSession().setAttribute("username", shiroUser.getAccount());
		LogManager.me().executeLog(LogTaskFactory.loginLog(shiroUser.getId(), getIp()));
		ShiroKit.getSession().setAttribute("sessionFlag", true);
		String key = SystemConstans.USER_SESSION_CHANGE.replaceAll("\\{0\\}", username);
		String string = keyValueDAO.get(key);
		if (StringUtil.isNotBlank(string)) {
			keyValueDAO.delete(key);
		}
		return SuccessTip.buildSuccess(shiroUser);
	}

	/**
	 * @api {GET} /restApi/logout 登出
	 * @apiVersion 1.0.0
	 * @apiGroup system
	 * @apiName logout
	 * @apiSuccessExample {json} Success-Response:
	 *                    HTTP/1.1 200 OK
	 *                    {
	 *                    "code": 200,
	 *                    "message": "成功"
	 *                    }
	 */
	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	public Object logOut() {

		ShiroUser user = ShiroKit.getUser();
		// LogManager.me().executeLog(LogTaskFactory.exitLog(user.getId(), getIp()));

		String key = SystemConstans.USER_ACOUNT_SESSIONID.replaceAll("\\{0\\}", user.getAccount());
		String changePass = SystemConstans.USER_SESSION_STATUS.replaceAll("\\{0\\}", HttpKit.getRequest().getSession().getId());
		String changeUser = SystemConstans.USER_SESSION_CHANGE.replaceAll("\\{0\\}", user.getAccount());
		keyValueDAO.delete(key);
		keyValueDAO.delete(changePass);
		keyValueDAO.delete(changeUser);
		ShiroKit.getSubject().logout();
		return SuccessTip.buildSuccess();
	}

	/**
	 * 过滤
	 */
	@RequestMapping(value = "/")
	public Object index(Map<String, Object> model) {

		// 获取菜单列表
		List<Integer> roleList = ShiroKit.getUser().getRoleList();
		if (roleList == null || roleList.size() == 0) {
			ShiroKit.getSubject().logout();
			model.put("tips", "该用户没有角色，无法登陆");
			return model;
		}
		List<MenuNode> menus = menuDao.getMenusByRoleIds(roleList);
		List<MenuNode> titles = MenuNode.buildTitle(menus);
		titles = ApiMenuFilter.build(titles);

		model.put("titles", titles);

		// 获取用户头像
		Integer id = ShiroKit.getUser().getId();
		User user = userMapper.selectById(id);
		String avatar = user.getAvatar();
		model.put("avatar", avatar);

		return model;
	}

	/**
	 * @api {GET} /restApi/kaptcha 验证码
	 * @apiVersion 1.0.0
	 * @apiGroup system
	 * @apiName kaptcha
	 */
	@RequestMapping("/kaptcha")
	public void index(HttpServletRequest request, HttpServletResponse response) {

		HttpSession session = request.getSession();

		response.setDateHeader("Expires", 0);

		// Set standard HTTP/1.1 no-cache headers.
		response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");

		// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
		response.addHeader("Cache-Control", "post-check=0, pre-check=0");

		// Set standard HTTP/1.0 no-cache header.
		response.setHeader("Pragma", "no-cache");

		// return a jpeg
		response.setContentType("image/jpeg");

		// create the text for the image
		String capText = producer.createText();

		// store the text in the session
		session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);

		// create the image with the text
		BufferedImage bi = producer.createImage(capText);
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// write the data out
		try {
			ImageIO.write(bi, "jpg", out);
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			try {
				out.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
